package com.sparrow.common.thread;

import com.sparrow.common.thread.executor.IoThreadPoolExecutor;
import com.sparrow.common.thread.runnable.NamedRunnable;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import java.util.concurrent.*;

/**
 * 该类用于管理和操作一个IO线程池，实现了Spring的DisposableBean接口，以便在销毁时正确关闭线程池。
 */
public class IoThreadPool implements DisposableBean {

    // 日志记录器，用于记录线程池的相关信息
    private static final Logger logger = LoggerFactory.getLogger(IoThreadPool.class);

    // 线程池执行器，负责实际的任务执行和管理
    private final IoThreadPoolExecutor threadPoolExecutor;

    /**
     * 默认构造函数，使用默认的核心线程数和最大线程数初始化线程池。
     */
    public IoThreadPool() {
        this(32, 128);
    }

    /**
     * 带参数的构造函数，允许指定核心线程数和最大线程数来初始化线程池。
     *
     * @param corePoolSize    线程池的核心线程数
     * @param maximumPoolSize 线程池的最大线程数
     */
    public IoThreadPool(int corePoolSize, int maximumPoolSize) {
        threadPoolExecutor = new IoThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(50000),
                new DefaultThreadFactory("io-thread"),
                new IoRejectHandler()
        );
    }

    /**
     * 执行指定名称的任务。
     *
     * @param taskName 任务的名称
     * @param runnable 要执行的任务
     */
    public void execute(String taskName, Runnable runnable) {
        this.threadPoolExecutor.execute(new NamedRunnable(taskName, runnable));
    }

    /**
     * 实现DisposableBean接口的destroy方法，用于在Spring容器销毁时关闭线程池。
     *
     * @throws Exception 如果在关闭线程池过程中发生异常
     */
    @Override
    public void destroy() throws Exception {
        this.threadPoolExecutor.shutdown();
        this.threadPoolExecutor.awaitTermination(30, TimeUnit.MINUTES);
        logger.info("io线程池关闭");
    }

    public Executor getExecutor() {
        return threadPoolExecutor;
    }

    /**
     * 自定义的拒绝策略类，当线程池无法接受新任务时，直接在调用者线程中执行该任务。
     */
    private static class IoRejectHandler implements RejectedExecutionHandler {

        /**
         * 当任务被线程池拒绝时，此方法会被调用。
         *
         * @param r        被拒绝的任务
         * @param executor 拒绝任务的线程池执行器
         */
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            r.run();
        }
    }
}